import { _decorator, Node, find, Animation, AnimationState, ICollisionEvent, Prefab, v3, SkinnedMeshRenderer, Material, BoxCollider, CCInteger, math, Vec3 } from 'cc';
import { CharacterController, CharacterFace } from './CharacterController';
import { PoolManager } from './AshFramework/Managers/PoolManager';
import { ItemController } from './ItemController';
import { Constant } from './AshFramework/Datas/Constant';
import { NodeUtil } from './AshFramework/Utils/NodeUtil';
import { GameController } from './GameController';
import { HPBar } from './AshFramework/UI/HPBar';
import { DataManager } from './AshFramework/Managers/DataManager';
import { DamageText } from './AshFramework/UI/DamageText';
import { ZTool } from './AshFramework/Utils/ZTool';
import { ResourceUtil } from './AshFramework/Utils/ResourceUtil';
import { ItemData, PlayerData } from './Data';
import { CharacterState } from './PlayerController';
import { EnemyAimController } from './EnemyAimController';
import { GameManager } from './GameManager';
import { AudioManager, Audios } from './AshFramework/Managers/AudioManager';
import Banner from './Banner';
const { ccclass, property } = _decorator;

const screenPosition = v3();
const position = v3();

@ccclass('EnemyController')
export class EnemyController extends CharacterController {
    @property(Node)
    hand: Node;

    @property(SkinnedMeshRenderer)
    SkinnedMeshRenderer: SkinnedMeshRenderer;

    @property([BoxCollider])
    colliders: BoxCollider[] = [];

    @property(Prefab)
    hpBarPrefab: Prefab;
    hpBar: HPBar;

    @property(CCInteger)
    lv: number = 1;

    aimCtrl: EnemyAimController;

    itemIndex: number = 0;

    NeedDestroyItem: boolean = false;

    positionY: number = 0;

    private _hp: number = 100;
    get HP() {
        return this._hp;
    }
    set HP(value: number) {
        this._hp = ZTool.Clamp(value, 0, value);
        this.hpBar.Set(this._hp / PlayerData.HPs[this.lv]);

        if (this._hp <= 0) {
            this.PlayAni(CharacterState.Down);
            this.hpBar.node.active = false;
            this.collider.enabled = false;
            this.rigidBody.enabled = false;
            for (let i = 0; i < this.colliders.length; i++) {
                this.colliders[i].enabled = false;
            }
            this.IsDead = true;
        }
    }

    onLoad() {
        super.onLoad();
        this.aimCtrl = this.node.getComponent(EnemyAimController)
        this.hpBar = NodeUtil.Instantiate(this.hpBarPrefab, find("Canvas")).getComponent(HPBar);
        this.hpBar.Init(1, this.lv, PlayerData.HPs[this.lv]);
        this.HP = PlayerData.HPs[this.lv];
        this.positionY = ZTool.GetRandom(-50, 50);
    }

    Shoot() {
        this.NeedDestroyItem = false;

        let data = DataManager.itemDatas[ZTool.GetRandomInt(0, DataManager.itemDatas.length)];
        this.itemIndex = data.Index;

        this.hand.children.forEach(e => PoolManager.PutNode(e));

        this.PlayAni(CharacterState.HandItem);

    }

    Display() {
        this.hpBar.node.active = false;
    }

    SetFace(index: CharacterFace) {
        ResourceUtil.Load(`Materials/Face_${index}`, Material, (err, mat) => {
            if (err) {
                console.error(err);
                return;
            }
            this.SkinnedMeshRenderer.setMaterial(mat, 1);
        })
    }
    popupAdIndex: number = 0;

    ChangeFaceToNormal(second: number = 2) {
        this.unschedule(this.SetFaceToNormal);
        this.schedule(this.SetFaceToNormal, second);
    }

    SetFaceToNormal() {
        this.SetFace(CharacterFace.高兴);
    }

    onAnimationFinishedEvent(type: Animation.EventType, state: AnimationState) {
        switch (state.name) {
            case CharacterState.Hit:
            case CharacterState.Throw:
                this.PlayAni(CharacterState.Idle);
                break;

            case CharacterState.HandItem:
                PoolManager.GetNode("Prefabs/ItemController", this.hand).then((node: Node) => {
                    if (this.NeedDestroyItem) {
                        PoolManager.PutNode(node);
                        return;
                    }

                    let data = GameManager.Instance.GetItemData(this.itemIndex);

                    node.getComponent(ItemController).Init(this.itemIndex, data.Damages[this.lv], true);

                    this.scheduleOnce(() => {
                        let x = ZTool.GetRandom(0, 1.5) * (math.random() > 0.5 ? -1 : 1);
                        let y = ZTool.GetRandom(0.5, 1) * -1;
                        let targetPos = v3(
                            GameController.Instance.player.node.worldPosition.x + x,
                            GameController.Instance.player.node.worldPosition.y + y,
                            GameController.Instance.player.node.worldPosition.z,
                        );
                        this.aimCtrl.fire(targetPos);
                    }, 1)
                });
                break;
            case CharacterState.Down:
                GameController.Instance.CheckWin();
                break;
        }

    }

    AnimFrameEvent(param: string) {
        switch (param) {
        }
    }

    DestroyItem() {
        this.NeedDestroyItem = true;
        this.hand.children.forEach(e => PoolManager.PutNode(e));
    }

    update(dt: number) {
        super.update(dt);
        screenPosition.set(GameController.Instance.WorldToScreen(this.node.worldPosition));
        this.hpBar.node.setPosition(screenPosition.x, screenPosition.y + 250 + this.positionY);
    }

    onCollisionEnter(event: ICollisionEvent) {
        if (this.IsDead) return;

        switch (event.otherCollider.getGroup()) {
            case Constant.Group.Item:
                let itemCtrl = event.otherCollider.node.parent.getComponent(ItemController);

                Banner.Instance.VibrateShort();

                if (itemCtrl && ItemData.IsKnife(itemCtrl.index)) {
                    itemCtrl.RigidEnable(false);
                    itemCtrl.node.setParent(event.selfCollider.node);
                    event.contacts[0].getWorldNormalOnB(position);
                    itemCtrl.itemNode.forward = position.negative();
                    event.contacts[0].getWorldPointOnB(position);
                    itemCtrl.itemNode.setWorldPosition(position);
                    itemCtrl.itemNode.setWorldScale(itemCtrl.worldScale);
                    AudioManager.PlaySound(Audios.Hit);
                } else {
                    AudioManager.PlaySound(Audios.Hit_2);
                }

                //飘字
                event.contacts[0].getWorldPointOnB(position);
                position.set(GameController.Instance.WorldToScreen(position));
                PoolManager.GetNode(Constant.Path.DamageText, find("Canvas"), position).then(node => {
                    this.HP -= itemCtrl.damage;
                    node.getComponent(DamageText).Show(`-${itemCtrl.damage}`);
                    this.SetFace(CharacterFace.痛苦);
                    this.ChangeFaceToNormal();
                });
                this.PlayAni(CharacterState.Hit);
                break;

        }
    }

    protected onEnable(): void {
        super.onEnable();

        for (let i = 0; i < this.colliders.length; i++) {
            this.colliders[i].on('onCollisionEnter', this.onCollisionEnter, this);
        }
    }

    protected onDisable(): void {
        super.onDisable();

        for (let i = 0; i < this.colliders.length; i++) {
            this.colliders[i].off('onCollisionEnter', this.onCollisionEnter, this);
        }
    }
}